#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include "semlib.h"  // 包含之前定义的信号量操作函数
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>

#define BUFFER_SIZE  2048

int main()
{
    pid_t pid;
    int sem_id; // 信号量ID 
    int shmid;  // 共享内存ID
    char *shm_addr = NULL; // 共享内存的地址
    char buff[40]; // 用于存储输入的字符串
    int i = 0;

    // 获取信号量ID，如果信号量不存在则创建
    sem_id = semget(ftok(".", 'a'), 1, 0666 | IPC_CREAT);
    if (sem_id == -1) {
        perror("semget");
        return -1;
    }

    // 初始化信号量，初始值为0
    if (init_sem(sem_id, 0) == -1) {
        return -1;
    }

    // 获取共享内存ID
    if ((shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0) {
        perror("shmget");
        return -1;
    }

    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        return -1;
    } else if (pid == 0) {
        // 子进程代码
        // 附加共享内存
        if ((shm_addr = (char *)shmat(shmid, 0, 0)) == (char *)-1) {
            perror("shmat");
            return -1;
        }

        // 循环3次从共享内存读取数据
        while (i < 3) {
            printf("Child process is waiting for data:\n");
            // P操作，等待信号量
            if (sem_p(sem_id) == -1) {
                return -1;
            }
            // 从共享内存读取数据
            strcpy(buff, shm_addr);
            printf("Child get data from shared-memory: %s\n", buff);
            // V操作，释放信号量
            if (sem_v(sem_id) == -1) {
                return -1;
            }
            i++;
        }

        // 删除信号量
        if (del_sem(sem_id) == -1) {
            return -1;
        }

        // 分离共享内存
        if ((shmdt(shm_addr)) < 0) {
            perror("shmdt");
            return -1;
        }

        // 删除共享内存
        if (shmctl(shmid, IPC_RMID, NULL) == -1) {
            perror("child process delete shared memory ");
            return -1;
        }
    } else {
        // 父进程代码
        // 附加共享内存
        if ((shm_addr = (char *)shmat(shmid, 0, 0)) == (char *)-1) {
            perror("Parent shmat failed");
            return -1;
        }

        // 循环3次向共享内存写入数据
        while (i < 3) {
            printf("Please input some string:\n");
            // 从标准输入读取数据
            fgets(buff, BUFFER_SIZE, stdin);
            // 将数据写入共享内存
            strncpy(shm_addr, buff, strlen(buff));
            // V操作，释放信号量
            if (sem_v(sem_id) == -1) {
                return -1;
            }
            i++;
            // P操作，等待信号量
            if (sem_p(sem_id) == -1) {
                return -1;
            }
        }

        // 分离共享内存
        if ((shmdt(shm_addr)) < 0) {
            perror("Parent:shmdt");
            return -1;
        }

        // 等待子进程结束
        waitpid(pid, NULL, 0);
    }
    return 0;
}